import json
from docker import Client
from io import BytesIO
import signal
import paramiko

cli = Client(base_url='unix://var/run/docker.sock')


class TimeoutError(Exception):
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return repr(self.value)


class timeout:
    def __init__(self, seconds=1, error_message='Timeout'):
        self.seconds = seconds
        self.error_message = error_message
    def handle_timeout(self, signum, frame):
        raise TimeoutError(self.error_message)
    def __enter__(self):
        signal.signal(signal.SIGALRM, self.handle_timeout)
        signal.alarm(self.seconds)
    def __exit__(self, type, value, traceback):
        signal.alarm(0)

d = {}

def build(dockerfile, tag):
    f = BytesIO(dockerfile.encode('utf-8'))
    try:
        res = cli.build(fileobj=f, rm=True, tag=tag, timeout=1)

        response = ""
        for line in res:
            obj = json.loads(line)
            if obj.get('stream') is not None:
                response += obj['stream']
            elif obj.get('error') is not None:
                response += obj['error']
    except:
        return "Timeout."
    return response


def run(tag, container_port, host_port):
    if container_port is not None and host_port is not None:
        container = cli.create_container(
            image=tag,
            ports=[container_port],
            host_config=cli.create_host_config(port_bindings={
                container_port: host_port,
            })
        )
    else:
        container = cli.create_container(image=tag)
    try:
        cli.start(container=container.get('Id'))
    except:
        return None
    return container.get('Id')


def logs(id):
    return cli.logs(container=id)


def stop(id):
    cli.stop(container=id, timeout=1)